package com.tennis.tennisreservation.service.impl;

import com.tennis.tennisreservation.config.WxPayConfig;
import com.tennis.tennisreservation.service.PaymentService;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import lombok.RequiredArgsConstructor;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;
import java.util.*;

import org.apache.http.util.EntityUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.security.Signature;
import java.security.PrivateKey;
import java.io.InputStream;
import java.util.Base64;

/**
 * 微信支付实现类
 */
@Service
@RequiredArgsConstructor
public class PaymentServiceImpl implements PaymentService {

    private final WxPayConfig wxPayConfig;
    private final CloseableHttpClient wechatPayHttpClient;
    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public Map<String, String> createJsapiOrder(String openid, Long amount, String description) {
        try {
            // 构建请求参数
            Map<String, Object> params = new HashMap<>();
            params.put("appid", wxPayConfig.getAppid());
            params.put("mchid", wxPayConfig.getPay().getMchId());
            params.put("description", description);
            params.put("notify_url", wxPayConfig.getPay().getNotifyUrl());

            // 订单号
            String outTradeNo = UUID.randomUUID().toString().replace("-", "");
            params.put("out_trade_no", outTradeNo);

            // 金额（单位分）
            Map<String, Object> amountMap = new HashMap<>();
            amountMap.put("total", amount);
            params.put("amount", amountMap);

            // 支付者 openid
            Map<String, Object> payer = new HashMap<>();
            payer.put("openid", openid);
            params.put("payer", payer);

            // 调用统一下单 API
            HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi");
            httpPost.addHeader("Accept", "application/json");
            httpPost.addHeader("Content-type", "application/json; charset=utf-8");

            StringEntity entity = new StringEntity(objectMapper.writeValueAsString(params), StandardCharsets.UTF_8);
            httpPost.setEntity(entity);

            try (CloseableHttpResponse response = wechatPayHttpClient.execute(httpPost)) {
                String bodyAsString = EntityUtils.toString(response.getEntity());
                Map<String, Object> resultMap = objectMapper.readValue(bodyAsString, Map.class);
                String prepayId = (String) resultMap.get("prepay_id");

                // 返回前端调起微信支付所需的参数
                Map<String, String> payParams = new HashMap<>();
                
                // 准备JSAPI调用参数
                String timeStamp = String.valueOf(System.currentTimeMillis() / 1000);
                String nonceStr = UUID.randomUUID().toString().replace("-", "");
                String packageValue = "prepay_id=" + prepayId;
                
                // 添加必要的参数
                payParams.put("timeStamp", timeStamp);
                payParams.put("nonceStr", nonceStr);
                payParams.put("package", packageValue);
                payParams.put("signType", "RSA");
                
                // 计算签名
                String signatureStr = wxPayConfig.getAppid() + "\n"
                                    + timeStamp + "\n"
                                    + nonceStr + "\n"
                                    + packageValue + "\n";
                
                // 签名
                try {
                    byte[] message = signatureStr.getBytes(StandardCharsets.UTF_8);
                    Signature signature = Signature.getInstance("SHA256withRSA");
                    
                    // 获取私钥
                    signature.initSign(getPrivateKey());
                    signature.update(message);
                    
                    String paySign = Base64.getEncoder().encodeToString(signature.sign());
                    payParams.put("paySign", paySign);
                } catch (Exception e) {
                    throw new RuntimeException("签名计算失败：" + e.getMessage(), e);
                }
                
                return payParams;
            }
        } catch (Exception e) {
            throw new RuntimeException("统一下单失败：" + e.getMessage(), e);
        }
    }
    
    /**
     * 加载商户私钥（从配置中获取）
     */
    private PrivateKey getPrivateKey() throws Exception {
        String path = wxPayConfig.getPay().getPrivateKeyPath();
        if (path.startsWith("classpath:")) {
            path = path.substring("classpath:".length());
            org.springframework.core.io.Resource resource = new org.springframework.core.io.ClassPathResource(path);
            try (InputStream inputStream = resource.getInputStream()) {
                return com.wechat.pay.contrib.apache.httpclient.util.PemUtil.loadPrivateKey(inputStream);
            }
        } else {
            java.io.FileInputStream fis = new java.io.FileInputStream(path);
            return com.wechat.pay.contrib.apache.httpclient.util.PemUtil.loadPrivateKey(fis);
        }
    }
}
